local GM = GM or gmod.GetGamemode()

GM.lootventory = {}
local linv = GM.lootventory

GM.buildingdata = {}

usermessage.Hook("wsBarrel",function(msg)
	local self = gmod.GetGamemode()
	
	local id = msg:ReadLong()
	local class = msg:ReadString()
	local oent = msg:ReadEntity()
	local bd = self.buildingdata[id]
	
	if not bd then	
		wsUID = wsUID + 1
		bd = {
			sv_wsUID = id,
			wsUID = id,
		}
		self.buildingdata[id] = bd
	end
	
	bd.ent = oent
	bd.class = class
	bd.inventory = {}
	
	local numitems = msg:ReadShort()
	if numitems > 0 then
		for i = 1,numitems do
			local class = msg:ReadString()
			local dat = bd.inventory[class]
			if not dat then
				dat = {
					item = self.items[class],
				}
				bd.inventory[class] = dat
			end
			
			dat.quantity = msg:ReadShort()
		end
	end
	
	//Open the GUI if it isn't already //TODO: Where we checkin'?
	linv.openInventory(id)
end)

usermessage.Hook("wsBarUpd",function(msg)
	local self = gmod.GetGamemode()
	local id = msg:ReadLong()
	
	if linv.menuInventory[id] then
		RunConsoleCommand("wsBarReq",id) //WE'RE STILL OPEN, HIT ME WITH THE DIGITS CUZ I'M A FA* LIKE THAT
	end
end)

usermessage.Hook("wsBarOOR",function(msg)
	local self = gmod.GetGamemode()
	local id = msg:ReadLong()
	
	linv.closeInventory(id)
	LocalPlayer():ChatPrint("Out of range for inventory transaction.") --"TODO: IMPORTANT, MAKE THIS NOT FAIL SO HARD
end)

//The actual GUI

linv.menuInventory = {}

linv.openInventory = function(id)
	local self = gmod.GetGamemode()
	local bd = self.buildingdata[id]
	
	if not (bd and bd.inventory) then
		return
	end
	
	local tab = linv.menuInventory[id]
	if type(tab) == "table" and tab.main then
		return
	end
	
	self.inventory.openInventory()
	
	local menu = {}
	linv.menuInventory[id] = menu //Declared hear to up table.Count
	menu.main = self.genwhitegui("Inventory")
		menu.main:SetName("menu.main")
		menu.main:SetPos(math.max(0,ScrW()*.5-512),ScrH()*.5-256)
		menu.main:SetPos(96+318*table.Count(linv.menuInventory),ScrH()-627)
		menu.main:SetSize(276+10+32,364+35)
		menu.main:SetVisible(true)
		menu.main.OnKeyCodePressed = function(self,char)
			/*
			//Msg("KEYCODE: ",char,"\n")
			local GM = gmod.GetGamemode()
			
			//TODO: Fetch id
			
			if char == 13 or char == 32 then //c or v
				GM.lootventory.closeInventory(id)
			end
			*/
			
			//Let the main inventory handle this shizz
			local GM = gmod.GetGamemode()
			if GM.inventory.menuInventory then
				GM.inventory.menuInventory.main:OnKeyCodePressed(char)
			end
		end
	menu.panel = vgui.Create("gmLootventory",menu.main,"gmLootventory")
		menu.panel:SetPos(5,30)
		menu.panel:SetSize(276+32,492)
		menu.panel:SetVisible(true)
	//linv.menuInventory[id] = menu //Already did this above
	menu.main:GetTable().dat = menu
	
	menu.id = id
	menu.bd = bd
end

linv.closeInventory = function(id)
	local tab = linv.menuInventory[id]
	if type(tab) == "table" and tab.main then
		tab.main:Remove()
	end
	linv.menuInventory[id] = nil
end

linv.closeAll = function()
	for k,v in pairs(linv.menuInventory) do
		linv.closeInventory(k)
	end
end

linv.isMouseOver = function(id) //Accepts an ID or nothing at all
	local tab = id and {id = linv.menuInventory[id]} or linv.menuInventory
	
	local m = {}
	m.x,m.y = gui.MousePos()
	
	for uid,menu in pairs(tab) do
		if menu.main and menu.main:IsVisible() then
			local x,y = menu.main:GetPos()
			local w,h = menu.main:GetSize()
			
			if m.x > x and m.x < x+w and m.y > y and m.y < y+h then
				return true //uid //Don't return uid because we can't determine order easily
			end
		else
			linv.closeInventory(uid)
		end
	end
end

hook.Add("HUDPaint","wslootinvreset",function()
	local GM = gmod.GetGamemode()
	//linv.active = nil
	GM.invdrag.itemto = nil
end)

linv.menuInvPanel = {
	Init = function(self)
		local dat = self:GetParent():GetTable()
		dat.m = {
			x=0,
			y=0,
			c={},
			f=0,
		}
		dat.scroll = 0
	end,
	Paint = function(self)
		local GM = gmod.GetGamemode()
		GM.invsel.last = UnPredictedCurTime()
		local dat = self:GetParent():GetTable()
		local m = dat.m
		
		//surface.SetDrawColor(255,255,255,255)
		//surface.DrawRect(0,0,self:GetWide(),self:GetTall())
		
		//Inventory box
		local ix = 0
		local iy = 20
		local iw = self:GetWide()-32
		local ih = self:GetTall()-128-20
		
		//Inventory
		local inventory = dat.dat.bd.inventory
		
		//GM.inventory.hover = nil
		
		local x = {
			p = 1,
			m = 0,
			s = 64,
			b = 4,
		}
		local y = {
			p = 1,
			m = 0,
			s = 64,
			b = 4,
		}
		//lawl, PMS
		
		x.m = math.floor(iw/(x.s+x.b))
		y.m = math.floor(ih/(y.s+y.b))
		
		//Calculate mouse position
		local mx, my
		if m.x > ix and m.x < ix+iw and m.y > iy and m.y < iy+ih then
			mx = m.x-ix-4
			my = m.y-iy-4
			
			local mrx = mx%(x.s+x.b)
			local mry = my%(y.s+y.b)
			
			if mrx <= x.s and mry <= y.s then
				mx = math.floor(mx/(x.s+x.b))+1
				my = math.floor(my/(y.s+y.b))+1
			end
		end
		local active
		if mx then
			//linv.active = dat.dat.id
			GM.invdrag.itemto = dat.dat.id
			GM.invdrag.itemtolabel = GM.items[dat.dat.bd.class].label
		end
		active = GM.invdrag and GM.invdrag.item and GM.invdrag.itemfrom ~= dat.dat.id and mx or false
		
		//Inventory draw
		draw.RoundedBox(4,ix,iy,iw,ih,(not active) and Color(0,0,0,100) or Color(0,0,255,100))
		//Continue
		
		draw.DrawText(tostring(GM.items[dat.dat.bd.class].label),"Trebuchet18",8,2,Color(255,255,255,255),0)
		
		local maxrows,rows
		
		//Scrollbar
		maxrows = y.m
		rows = math.max(math.ceil(#inventory/x.m),maxrows)
		//Etc
		
		local desc = {
		}
		
		for k,v in pairs(inventory) do
			/*
			if not debugbeagle then
				debugbeagle = true
				//PrintTable(inventory)
			end
			*/
			if x.p > x.m then
				x.p = 1
				y.p = y.p+1
			end
			if y.p > y.m then
				x.p = x.m+1
				y.p = y.p-1
				break
			end
			
			
			local px = x.b+ix+(x.p-1)*(x.s+x.b)
			local py = y.b+iy+(y.p-1)*(y.s+y.b)
			local pw = x.s
			local ph = y.s
			
			local col = Color(0,0,0,63)
			if x.p == mx and y.p == my then
				col = Color(0,0,255,63)
				
				desc.x = x.b+ix
				desc.y = py+y.s+y.b
				desc.w = iw-x.b*2
				desc.h = y.s+y.b+y.s
				desc.item = v.item
				
				//GM.inventory.hover = v.item
				
				if m.c[0] == 1 then
					m.c[0] = 2
					m.f = {"invdrag",k}
					GM.invdrag.item = v.item
					GM.invdrag.itemfrom = dat.dat.id
					GM.invdrag.itemfromlabel = GM.items[dat.dat.bd.class].label
				end
			end
			
			surface.SetDrawColor(col.r,col.g,col.b,col.a)
			surface.DrawRect(px,py,pw,ph)
			
			v.item:onInvPaint(px,py,pw,ph,nil,{quantity = v.quantity})
			
			x.p = x.p+1
		end
		
		//Inventory description
		
		if desc.item then
			surface.SetDrawColor(0,0,0,230)
			surface.DrawRect(desc.x,desc.y,desc.w,desc.h)
			
			local item = desc.item
			draw.DrawText(item.label,"Trebuchet24",4+desc.x,desc.y,Color(255,255,255,230),0)
			draw.DrawText(string.format("%.2f",item.weight) .. " kg","Trebuchet24",desc.x+desc.w-4,desc.y+desc.h-24,Color(255,255,255,230),2)
			
			//Word wrap
			surface.SetFont("Trebuchet18")
			
			local dp = string.Explode(" ",item.description)
			local dout = dp[1]
			local curline = dout
			for k,v in pairs(dp) do
				if k ~= 1 then
					local sz = surface.GetTextSize(curline)
					local sza = surface.GetTextSize(" "..v)
					if sz+sza < desc.w then
						dout = dout .. " " .. v
						curline = curline .. " " .. v
					else
						dout = dout .. "\n" .. v
						curline = v
					end
				end
			end
			draw.DrawText(dout or "","Trebuchet18",4+desc.x,desc.y+24,Color(255,255,255,230),0)
		end
		
		//Scrollbar
		do
			draw.RoundedBox(4,ix+iw+4,iy,32-4,ih,Color(0,0,0,100))
			
			
			local inch = 1/rows
			local disp = maxrows*inch
			
			local dp = {
				x = ix+iw+4+4,
				y = iy+4,
				w = 32-4-8,
				h = (ih-8),
			}
			local d = {
				uid = 1,
				x = dp.x,
				y = dp.y+dat.scroll*inch*dp.h,
				w = dp.w,
				h = dp.h*disp,
			}
			local col = Color(0,0,0,100)
			
			if m.y >= dp.y and m.y <= dp.y+dp.h then
				if m.x >= d.x and m.x <= d.x+d.w then
					col = Color(0,0,255,100)
					if m.c[0] == 1 then
						m.c[0] = 2
						m.f = {"scroll",m.y-d.y}
					end
				end
				if m.c[0] == 2 and type(m.f) == "table" and m.f[1] == "scroll" then
					dat.scroll = math.Clamp(math.Round((m.y-m.f[2]-dp.y)/inch/dp.h),0,math.max(0,rows-maxrows))
					col = Color(255,0,0,100)
				end
			end
			
			draw.RoundedBox(4,d.x,d.y,d.w,d.h,col)
			
		end
		
		//Mouse reset
		for k,v in pairs(m.c) do
			if v == 1 or v == -1 then
				//if type(m.f) == "table" and m.f[1] == "invdrag" then
				//	GM.invdrag.item = nil
				//end
				m.c[k] = 0
				m.f = 0
			end
		end
	end,
	OnCursorMoved = function(self,x,y)
		self:GetParent():GetTable().m.x = x
		self:GetParent():GetTable().m.y = y
	end,
	OnCursorExited = function(self)
		self:GetParent():GetTable().m.x = 0
		self:GetParent():GetTable().m.y = 0
		self:GetParent():GetTable().m.c[0] = 0
		self:GetParent():GetTable().m.c[1] = 0
		self:GetParent():GetTable().m.f = 0
	end,
	OnMousePressed = function(self,mc)
		if mc >= 107 then
			mc = mc - 107
		end
		if mc == 0 or mc == 1 then
			self:GetParent():GetTable().m.c[mc] = 1
			self:GetParent():GetTable().m.f = 0
		end
	end,
	OnMouseReleased = function(self,mc)
		//local GM = gmod.GetGamemode()
		if mc >= 107 then
			mc = mc - 107
		end
		if mc == 0 or mc == 1 then
			self:GetParent():GetTable().m.c[mc] = -1
			//GM.invdrag.m.c[mc] = -1
		end
	end,
	OnMouseWheeled = function(self,delta)
		local GM = gmod.GetGamemode()
		if GM.invdrag and GM.invdrag.item then
			delta = math.Round(math.Clamp(delta,-1,1))
			
			GM.invdrag.quantity = GM.invdrag.quantity or 1
			local invdat = GM.inv[GM.invdrag.item.class]
			local max = 1
			if invdat and GM.invdrag.itemfrom == -1 then
				max = invdat.quantity
			elseif GM.invdrag.itemfrom then
				local tab = GM.buildingdata[GM.invdrag.itemfrom]
				if tab then
					tab = tab.inventory[GM.invdrag.item.class]
					if tab and tab.quantity then
						max = tonumber(tab.quantity) or 1
					end
				end
			end
			GM.invdrag.quantity = math.Clamp(GM.invdrag.quantity + delta,1,max)
			
			return
		end
		local dat = self:GetParent():GetTable()
		local iw = self:GetWide()-32
		local ih = self:GetTall()-128-20
		local xm = math.floor(iw/(64+4))
		local ym = math.floor(ih/(64+4))
		local elements = #dat.dat.bd.inventory
		local rows = math.max(math.ceil(elements/xm),ym)
		
		if delta > 0 then
			dat.scroll = math.Clamp(dat.scroll - 1,0,math.max(0,rows-ym))
		else
			dat.scroll = math.Clamp(dat.scroll + 1,0,math.max(0,rows-ym))
		end
	end,
	OnCheckScroll = function(self)
		local dat = self:GetParent():GetTable()
		local iw = self:GetWide()-32
		local ih = self:GetTall()-128-20
		local xm = math.floor(iw/(64+4))
		local ym = math.floor(ih/(64+4))
		local elements = #dat.dat.bd.inventory
		local rows = math.max(math.ceil(elements/xm),ym)
		
		dat.scroll = math.Clamp(dat.scroll,0,math.max(0,rows-ym))
	end,
}

vgui.Register("gmLootventory",linv.menuInvPanel)
